package com.chenyun.boot.datasource.page;

import cn.hutool.core.collection.CollectionUtil;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chenyun.common.context.SpringContext;
import com.chenyun.common.utils.StringUtils;
import com.chenyun.common.vo.AjaxResult;
import com.chenyun.common.vo.PageFilter;
import com.chenyun.common.vo.PageResult;
import com.chenyun.common.vo.QueryPage;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModelProperty;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static cn.hutool.core.util.StrUtil.UNDERLINE;

/**
 * @author Lonni
 * @date 2021-05-02 16:42
 */
public class PageUtils {


    /**
     * 获取对象的数据库参数
     * @param aclass
     * @return
     * @throws JsonProcessingException
     */
    public static List<Map<String, String>> getFieldInMap(Class aclass) throws JsonProcessingException {
        String key = aclass.getName();
        RedisTemplate redisTemplate= SpringContext.getBean(StringRedisTemplate.class);
        Object o = redisTemplate.opsForValue().get(key);
        if (o == null) {
            //拿到所有的私有字段
            Field[] declaredFields = aclass.getDeclaredFields();
            List<Map<String, String>> fileMaps = Lists.newArrayList();
            for (Field f : declaredFields) {
                String fileName = f.getName();
                String dbName="";
                //拿到mybatis的注解
                TableField fieldAnnotion = f.getAnnotation(TableField.class);
                TableId idAnnotion = f.getAnnotation(TableId.class);
                //注解为空,表示使用默认命名 直接转换
                if (fieldAnnotion == null && idAnnotion == null) {
                    dbName= StringUtils.humpToUnderline(fileName);
                }else if (fieldAnnotion != null && fieldAnnotion.exist() == false) {
                    continue;
                }else {
                    dbName = idAnnotion == null ? fieldAnnotion.value() : idAnnotion.value();
                }
                String finalDbName = dbName;
                fileMaps.add(new HashMap<String, String>() {{
                    put("fileName", fileName);
                    put("dbName", finalDbName);
                }});
            }
            if (CollectionUtil.isNotEmpty(fileMaps)){
                //设置缓存
                redisTemplate.opsForValue().set(key, JSON.toJSONString(fileMaps), 5, TimeUnit.HOURS);
            }
            return fileMaps;
        } else {
            ObjectMapper mapper = new ObjectMapper();
            List<Map<String, String>> list = mapper.readValue(o.toString(), List.class);
            return list;
        }

    }


    public  static<T> PageResult getPageResult(IPage<T> page){
        PageResult pageResult=new PageResult();
        pageResult.setPageIndex(page.getCurrent());
        pageResult.setPage(page.getPages());
        pageResult.setPageSize(page.getSize());
        pageResult.setTotal(page.getTotal());
        pageResult.setData(page.getRecords());
        return  pageResult;
    }

    @Deprecated
    public static   PageResult getPageByList(Object list){
        PageResult pageResult=new PageResult();
        pageResult.setData(list);
        return  pageResult;
    }

    /**
     * 获取分业的结果
     * @param list 查询出的分页后结果
     * @param <T> 泛型
     * @return
     */
    public static<T> PageResult  getPageHelperByList (List<T> list){
        PageResult pageResult=new PageResult();
        PageInfo<T> info=new PageInfo<>(list);
        pageResult.setPageIndex(info.getPageNum());
        pageResult.setPage(info.getPages());
        pageResult.setPageSize(info.getPageSize());
        pageResult.setTotal(info.getTotal());
        pageResult.setData(info.getList());
        return  pageResult;
    }

    @Deprecated
    public static<T> AjaxResult getPageAjaxResult  (List<T> list){
        PageResult pageHelperByList = getPageHelperByList(list);
        return  AjaxResult.SUCCESS(pageHelperByList);
    }




    /**
     * 拿到wapper组装的对象
     * 直接使用前端传入的实体模型转换
     * @return
     */
    @ApiModelProperty(hidden = true)
    public static <T> QueryWrapper<T> getQueryWrapper(QueryPage queryPage){
        QueryWrapper<T> wrapper = new QueryWrapper<>();
        if (MapUtil.isEmpty(queryPage.getFilter())) {
            return wrapper;
        }
        queryPage.getFilter().forEach((key, filter) -> {
            String filedName="";
            if (key.contains(UNDERLINE)){
                filedName=key;
            }else {
                filedName= StringUtils.humpToUnderline(key);
            }
            assemblyConditions(wrapper,filter,filedName);
        });
        return wrapper;
    }

    /**
     * 拿到wapper组装的对象
     * 查询数据库实体方式
     * @return
     */
//    @Deprecated
//    @ApiModelProperty(hidden = true)
//    public QueryWrapper getQueryWrapper(List<Map<String, String>> classByT) {
//        QueryWrapper wrapper = new QueryWrapper<>();
//        if (MapUtil.isEmpty(filter)) {
//            return wrapper;
//        }
//        filter.forEach((key, filter) -> {
//            List<Map<String, String>> collect = classByT.stream().filter(p -> p.get("fileName").equals(key)).collect(Collectors.toList());
//            if (CollectionUtil.isEmpty(collect)) {
//                throw new RuntimeException("未找到查询的映射对象!");
//            }
//            String filedName = collect.get(0).get("dbName");
//            ConditionEnum byValue=filter.getFilter();
//            if (byValue == null) {
//                throw new RuntimeException("条件类型传入不合法!");
//            }
//            assemblyConditions(wrapper,filter,filedName);
//        });
//        return wrapper;
//
//
//    }


    private static void  assemblyConditions(QueryWrapper wrapper, PageFilter filter, String filedName){
        if (StringUtils.isBlank(filter.getValue())){
            return;
        }
        switch (filter.getFilter()) {
            //等于
            case eq:
                wrapper.eq(filedName, filter.getValue());
                break;
            //不等于
            case ne:
                wrapper.ne(filedName, filter.getValue());
                break;
            //小于等于
            case le:
                wrapper.le(filedName, filter.getValue());
                break;
            //大于等于
            case ge:
                wrapper.ge(filedName, filter.getValue());
                break;
            //大于
            case gt:
                wrapper.gt(filedName, filter.getValue());
                break;
            //小于
            case lt:
                wrapper.lt(filedName, filter.getValue());
                break;
            case like:
                wrapper.like(filedName, filter.getValue());
                break;
            case llike:
                wrapper.likeLeft(filedName, filter.getValue());
                break;
            case rlike:
                wrapper.likeRight(filedName, filter.getValue());
                break;
            case between:
                String[] split = filter.getValue().split(",");
                if (split.length < 2) {
                    throw new RuntimeException("传入的between条件必须存在值区间");
                } else {
                    wrapper.between(filedName, split[0], split[1]);
                }
                break;
            case in:
                List<Object> objects = JSON.parseArray(filter.getValue(), Object.class);
                if (CollectionUtil.isEmpty(objects)) {
                    throw new RuntimeException("包含查询必须传入列表值");
                }
                wrapper.in(filedName, objects);
                break;
            default:
                break;
        }
    }

}
